package com.zycfc.zsf.boot.exception.handler;

import org.springframework.web.servlet.mvc.method.annotation.*;
import com.zycfc.zsf.boot.exception.config.*;
import java.lang.reflect.*;
import javax.validation.*;
import com.zycfc.zsf.boot.exception.type.*;
import org.springframework.web.*;
import org.springframework.web.bind.*;
import org.springframework.web.multipart.support.*;
import org.springframework.web.servlet.*;
import org.springframework.beans.*;
import org.springframework.http.converter.*;
import org.springframework.web.context.request.async.*;
import com.zycfc.zsf.boot.util.text.*;
import com.zycfc.zsf.boot.exception.*;
import org.springframework.validation.*;
import javax.servlet.http.*;
import java.net.*;
import javax.servlet.*;
import com.zycfc.zsf.boot.util.json.*;
import java.util.*;
import java.io.*;
import org.slf4j.*;

public class ZsfExceptionHandler extends ResponseEntityExceptionHandler
{
    private static final Logger log;
    private static final String DEFAULT_MESSAGE = "";
    private static final String ERROR_SPLITER = ";";
    private static final String QUESTION = "?";
    private static final String AND = "&";
    private static final String EQUAL = "=";
    private static final String X_REQUESTED_WITH = "X-Requested-With";
    private static final String XML_HTTP_REQUEST = "XMLHttpRequest";
    private static final String ACCEPT = "Accept";
    private static final String CHAR_SET = "UTF-8";
    private static final String CONTENT_TYPE = "application/json;charset=UTF-8";
    private final ExceptionProperties properties;
    
    public ZsfExceptionHandler(final ExceptionProperties properties) {
        this.properties = properties;
    }
    
    public ExceptionInfo resolveException(Throwable throwable) {
        String message = "";
        String assembleMsg = null;
        if (throwable instanceof UndeclaredThrowableException) {
            final UndeclaredThrowableException undeclaredThrowable = (UndeclaredThrowableException)throwable;
            throwable = undeclaredThrowable.getUndeclaredThrowable();
        }
        IExceptionCode code;
        if (throwable instanceof BaseException) {
            final BaseException exception = (BaseException)throwable;
            code = exception.getCode();
            message = null;
            assembleMsg = exception.getCodeMsg();
        }
        else if (throwable instanceof ConstraintViolationException) {
            final ConstraintViolationException cve = (ConstraintViolationException)throwable;
            final Set<ConstraintViolation<?>> constraintViolationSet = (Set<ConstraintViolation<?>>)cve.getConstraintViolations();
            final StringBuilder errorMsgBuilder = new StringBuilder();
            final int size = constraintViolationSet.size();
            int i = 0;
            for (final ConstraintViolation<?> constraintViolation : constraintViolationSet) {
                if (this.properties.isShowErrorFieldName()) {
                    final String path = constraintViolation.getPropertyPath().toString();
                    final String separator = ".";
                    final int pos = path.lastIndexOf(separator);
                    if (pos == -1 || pos == path.length() - separator.length()) {}
                    final String field = path.substring(pos + separator.length());
                    errorMsgBuilder.append(field).append(":");
                }
                errorMsgBuilder.append(constraintViolation.getMessage());
                if (++i < size) {
                    errorMsgBuilder.append(";");
                }
            }
            code = (IExceptionCode)ExceptionCode.BAD_REQUEST;
            message = errorMsgBuilder.toString();
        }
        else if (throwable instanceof MethodArgumentNotValidException) {
            final MethodArgumentNotValidException mException = (MethodArgumentNotValidException)throwable;
            final BindingResult bindingResult = mException.getBindingResult();
            final List<ObjectError> errors = (List<ObjectError>)bindingResult.getAllErrors();
            final StringBuilder errorMsgBuilder = new StringBuilder();
            for (int size2 = errors.size(), j = 0; j < size2; ++j) {
                final ObjectError error = errors.get(j);
                String field2;
                String msg;
                if (error instanceof FieldError) {
                    final FieldError fError = (FieldError)error;
                    field2 = fError.getObjectName();
                    msg = fError.getDefaultMessage();
                }
                else {
                    field2 = error.getObjectName();
                    msg = error.getDefaultMessage();
                }
                if (this.properties.isShowErrorFieldName()) {
                    errorMsgBuilder.append(field2).append(":");
                }
                errorMsgBuilder.append(msg);
                if (j < size2 - 1) {
                    errorMsgBuilder.append(";");
                }
            }
            code = (IExceptionCode)ExceptionCode.BAD_REQUEST;
            message = errorMsgBuilder.toString();
        }
        else if (throwable instanceof BindException) {
            final BindException bEx = (BindException)throwable;
            final List<FieldError> errors2 = (List<FieldError>)bEx.getFieldErrors();
            final StringBuilder errorMsgBuilder2 = new StringBuilder();
            for (int size3 = errors2.size(), k = 0; k < size3; ++k) {
                final FieldError error2 = errors2.get(k);
                if (this.properties.isShowErrorFieldName()) {
                    errorMsgBuilder2.append(error2.getField()).append(":");
                }
                errorMsgBuilder2.append(error2.getDefaultMessage());
                if (k < size3 - 1) {
                    errorMsgBuilder2.append(";");
                }
            }
            code = (IExceptionCode)ExceptionCode.BAD_REQUEST;
            message = errorMsgBuilder2.toString();
        }
        else if (throwable instanceof HttpRequestMethodNotSupportedException || throwable instanceof HttpMediaTypeNotSupportedException || throwable instanceof HttpMediaTypeNotAcceptableException || throwable instanceof MissingPathVariableException || throwable instanceof MissingServletRequestParameterException || throwable instanceof ServletRequestBindingException || throwable instanceof TypeMismatchException || throwable instanceof HttpMessageNotReadableException || throwable instanceof MissingServletRequestPartException || throwable instanceof NoHandlerFoundException) {
            code = (IExceptionCode)ExceptionCode.BAD_REQUEST;
            message = throwable.getMessage();
        }
        else if (throwable instanceof ConversionNotSupportedException || throwable instanceof HttpMessageNotWritableException) {
            code = (IExceptionCode)ExceptionCode.INTERNAL_SERVER_ERROR;
            message = throwable.getMessage();
        }
        else if (throwable instanceof AsyncRequestTimeoutException) {
            code = (IExceptionCode)ExceptionCode.SERVICE_UNAVAILABLE;
            message = throwable.getMessage();
        }
        else if (throwable.getClass().getSimpleName().equals("HystrixRuntimeException")) {
            code = (IExceptionCode)ExceptionCode.SERVICE_UNAVAILABLE;
            message = throwable.getMessage();
        }
        else if (throwable.getClass().getSimpleName().equals("HttpStatusHystrixBadRequestException")) {
            code = (IExceptionCode)ExceptionCode.SERVICE_HTTP_STATUS_ERROR;
            message = throwable.getMessage();
        }
        else {
            code = (IExceptionCode)ExceptionCode.INTERNAL_SERVER_ERROR;
            if (this.properties.isReturnUnkownExceptionMessage()) {
                final String unkownExceptionMessage = this.properties.getUnkownExceptionMessage();
                if (null != unkownExceptionMessage && unkownExceptionMessage.length() > 0) {
                    message = unkownExceptionMessage;
                }
                else {
                    message = throwable.getMessage();
                }
            }
            if (null == message) {
                message = throwable.getClass().getName();
            }
        }
        String retMsg = code.getMessage();
        if (StringUtils.isNotEmpty(assembleMsg)) {
            retMsg = assembleMsg;
        }
        final ExceptionInfo info = new ExceptionInfo((String)code.getValue(), retMsg);
        info.setThrowable(throwable);
        ZsfExceptionHandler.log.error(info.getCode() + "##@##" + info.getMessage(), throwable);
        return info;
    }
    
    private boolean isAjax(final HttpServletRequest request) {
        final String xRequestedWith = request.getHeader("X-Requested-With");
        final String contentType = request.getHeader("Accept");
        return "XMLHttpRequest".equals(xRequestedWith) || (null != contentType && contentType.contains("application/json"));
    }
    
    public void sendErrorMsg(final HttpServletRequest request, final HttpServletResponse response, final ExceptionInfo info) throws Exception {
        String errorPageUrl = this.properties.getErrorPageUrl();
        try {
            final StringBuilder sb = new StringBuilder(info.getMessage());
            final Throwable throwable = info.getThrowable();
            if (throwable != null) {
                final StackTraceElement[] stackTrace;
                final StackTraceElement[] trace = stackTrace = throwable.getStackTrace();
                for (final StackTraceElement traceElement : stackTrace) {
                    sb.append("\r\n").append(traceElement.toString());
                }
            }
            final String errorStackTraceMgs = sb.toString();
            ZsfExceptionHandler.log.error("\u5f02\u5e38\u5806\u6808\u4fe1\u606f\u6253\u5370\uff1a\u3010{}\u3011", (Object)errorStackTraceMgs);
        }
        catch (Exception e) {
            ZsfExceptionHandler.log.error("\u5f02\u5e38\u76d1\u63a7\u7edf\u8ba1\u5931\u8d25", (Throwable)e);
        }
        if (this.isAjax(request) || null == errorPageUrl || errorPageUrl.length() == 0) {
            this.writeErrorMsg(response, info.getCode(), info.getMessage());
        }
        else {
            try {
                switch (this.properties.getSendErrorType()) {
                    case REDIRECT: {
                        if (!errorPageUrl.contains("?")) {
                            errorPageUrl += "?";
                        }
                        errorPageUrl = errorPageUrl + "&" + this.properties.getErrorMessageName() + "=" + URLEncoder.encode(info.getMessage(), this.properties.getCharSet()) + "&" + this.properties.getCodeName() + "=" + info.getCode();
                        response.sendRedirect(errorPageUrl);
                        break;
                    }
                    case FORWARD: {
                        if (StringUtils.isEmpty(errorPageUrl)) {
                            this.writeErrorMsg(response, info.getCode(), info.getMessage());
                            break;
                        }
                        request.setAttribute(this.properties.getCodeName(), (Object)info.getCode());
                        request.setAttribute(this.properties.getErrorMessageName(), (Object)info.getMessage());
                        request.getRequestDispatcher(errorPageUrl).forward((ServletRequest)request, (ServletResponse)response);
                        break;
                    }
                    default: {
                        ZsfExceptionHandler.log.error("unkown send error type:{}", (Object)this.properties.getSendErrorType());
                        this.writeErrorMsg(response, info.getCode(), info.getMessage());
                        break;
                    }
                }
            }
            catch (Exception e) {
                ZsfExceptionHandler.log.error(e.getMessage(), (Throwable)e);
            }
        }
    }
    
    private void writeErrorMsg(final HttpServletResponse response, final String code, final String message) throws Exception {
        if (response.isCommitted()) {
            return;
        }
        if (ExceptionCode.UNAUTHORIZED.getValue().equals(code)) {
            response.setStatus(401);
        }
        if (ExceptionCode.FORBIDDEN.getValue().equals(code)) {
            response.setStatus(403);
        }
        this.writeData(response, code, message);
    }
    
    private void writeData(final HttpServletResponse response, final String code, final String message) throws Exception {
        if (null == message || message.length() == 0) {
            return;
        }
        final Map<String, String> result = new HashMap<String, String>();
        result.put("code", code);
        result.put("message", message);
        response.setContentType("application/json;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        try (final PrintWriter out = response.getWriter()) {
            out.print(JsonUtils.objectToJson((Object)result));
            out.flush();
        }
        catch (Exception e) {
            ZsfExceptionHandler.log.error("writeData\u5f02\u5e38", (Throwable)e);
            throw e;
        }
    }
    
    static {
        log = LoggerFactory.getLogger((Class)ZsfExceptionHandler.class);
    }
}
